package org.ricks.virtual;

import org.ricks.ioc.utils.Logger;
import java.util.concurrent.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.LongAdder;

public class Player implements AutoCloseable {
    // 配置常量
    private static final int MAX_QUEUE_SIZE = 1000;
    private static final long SHUTDOWN_TIMEOUT_MS = 5000;
    private static final int QUEUE_SIZE_WARNING_THRESHOLD = 100;
    private static final long SLOW_TASK_THRESHOLD_NS = TimeUnit.MILLISECONDS.toNanos(1000);
    private static final long CRITICAL_SLOW_TASK_THRESHOLD_NS = TimeUnit.MILLISECONDS.toNanos(1000);
    private static final int MAX_CONSECUTIVE_SLOW_TASKS = 5;

    public final String id;

    // 使用有界队列避免内存溢出
    private final BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(MAX_QUEUE_SIZE);

    // 虚拟线程池替代单线程
    private final ExecutorService virtualThreadPool;

    // 使用LongAdder替代AtomicLong提高并发计数性能
    private final LongAdder rejectedTasks = new LongAdder();
    private final LongAdder processedTasks = new LongAdder();
    private final LongAdder totalProcessingTimeNs = new LongAdder();
    private final LongAdder slowTaskCount = new LongAdder();
    private final LongAdder criticalSlowTaskCount = new LongAdder();
    private final LongAdder consecutiveSlowTasks = new LongAdder();

    private volatile boolean isClosing = false;
    private final ReentrantLock shutdownLock = new ReentrantLock();


    // 使用玩家管理器进行资源管理

    public Player(String id) {
        this.id = id;

        // 创建虚拟线程池，充分利用虚拟线程优势
        this.virtualThreadPool = Executors.newThreadPerTaskExecutor(
                Thread.ofVirtual()
                        .name("player-", 0)
                        .factory()
        );

        startProcessing();
        PlayerManager.registerPlayer(this);
    }

    private void startProcessing() {
        virtualThreadPool.submit(() -> {
            while (!Thread.currentThread().isInterrupted() && !isClosing) {
                try {
                    Runnable task = taskQueue.poll(100, TimeUnit.MILLISECONDS);
                    if (task != null) {
                        task.run();
                        processedTasks.increment();
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    Logger.error("Player " + id + " unexpected error in task processing", e);
                    // 继续处理其他任务
                }
            }
            Logger.debug("Player " + id + " processing thread exited");
        });
    }

    private Runnable wrapTask(Runnable task) {
        return () -> {
            long startTime = System.nanoTime();
            try {
                task.run();
            } catch (Exception e) {
                Logger.error("Player " + id +  " failed", e);
                handleTaskFailure( e);
            } finally {
                long durationNs = System.nanoTime() - startTime;
                totalProcessingTimeNs.add(durationNs);

                // 慢任务检测（使用纳秒提高精度）
                if (durationNs > SLOW_TASK_THRESHOLD_NS) {
                    slowTaskCount.increment();
                    long consecutive = consecutiveSlowTasks.longValue();
                    consecutiveSlowTasks.increment();

                    if (durationNs > CRITICAL_SLOW_TASK_THRESHOLD_NS) {
                        criticalSlowTaskCount.increment();
                        Logger.warn("Player " + id + " CRITICAL SLOW " +
                                " executed in " + TimeUnit.NANOSECONDS.toMillis(durationNs) + "ms");
                    } else {
                        Logger.debug("Player " + id + " slow " +
                                " executed in " + TimeUnit.NANOSECONDS.toMillis(durationNs) + "ms");
                    }

                    // 连续慢任务报警
                    if (consecutive >= MAX_CONSECUTIVE_SLOW_TASKS) {
                        Logger.warn("Player " + id + " has " + consecutive +
                                " consecutive slow tasks, possible performance issue");
                    }
                } else {
                    consecutiveSlowTasks.reset(); // 重置连续慢任务计数
                }
            }
        };
    }

    private void handleTaskFailure(Exception e) {

        Logger.warn("Player " + id +  " failed, error: " + e.getMessage());
    }

    public CompletableFuture<Void> submitTaskAsync(Runnable task) {
        if (isClosing) {
            rejectedTasks.increment();
            Logger.warn("Player " + id + " is closing, task rejected");
            return CompletableFuture.failedFuture(new RejectedExecutionException("Player is closing"));
        }

        // 队列监控
        int pendingTasks = getPendingTasks();
        if (pendingTasks > QUEUE_SIZE_WARNING_THRESHOLD) {
            Logger.warn("Player " + id + " queue size " + pendingTasks + " exceeds warning threshold");
        }

        CompletableFuture<Void> future = new CompletableFuture<>();
        Runnable wrappedTask = wrapTask(() -> {
            try {
                task.run();
                future.complete(null);
            } catch (Exception e) {
                future.completeExceptionally(e);
                throw e;
            }
        });

        if (!taskQueue.offer(wrappedTask)) {
            rejectedTasks.increment();
            Logger.warn("Player " + id + " queue full, task rejected");
            future.completeExceptionally(new RejectedExecutionException("Task queue full"));
        }

        return future;
    }

    // 同步提交方法，兼容旧代码
    public void submitTask(Runnable task, boolean retryOnFull) {
        CompletableFuture<Void> future = submitTaskAsync(task);

        if (retryOnFull && future.isCompletedExceptionally()) {
            try {
                // 短暂等待后重试
                Thread.sleep(10);
                submitTaskAsync(task).get(100, TimeUnit.MILLISECONDS);
            } catch (Exception e) {
                rejectedTasks.increment();
                Logger.warn("Player " + id + " task submission failed after retry", e);
            }
        }
    }

    public void disconnect() {
        shutdownLock.lock();
        try {
            if (isClosing) {
                return;
            }
            isClosing = true;

            // 优雅关闭：先停止接受新任务，然后处理队列中剩余任务
            virtualThreadPool.shutdown();

            try {
                if (!virtualThreadPool.awaitTermination(SHUTDOWN_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
                    Logger.warn("Player " + id + " shutdown timed out, forcing shutdown");
                    List<Runnable> remainingTasks = virtualThreadPool.shutdownNow();
                    if (!remainingTasks.isEmpty()) {
                        Logger.warn("Player " + id + " discarded " + remainingTasks.size() + " pending tasks");
                        saveCriticalTasksData(remainingTasks);
                    }
                } else {
                    Logger.debug("Player " + id + " shutdown completed gracefully");
                }
            } catch (InterruptedException e) {
                virtualThreadPool.shutdownNow();
                Thread.currentThread().interrupt();
                Logger.warn("Player " + id + " shutdown interrupted", e);
            }
        } finally {
            PlayerManager.unregisterPlayer(this);
            shutdownLock.unlock();
        }
    }

    private void saveCriticalTasksData(List<Runnable> tasks) {
        // 提取关键任务数据并保存
        tasks.stream()
                .filter(task -> task.toString().contains("save-data") ||
                        task.toString().contains("transfer-resources"))
                .forEach(task -> {
                    Logger.info("Player " + id + " saving critical task: " + task);
                    // 实际实现中会解析任务内容并保存关键数据
                });
    }

    // 监控接口
    public int getPendingTasks() {
        return taskQueue.size();
    }

    public long getRejectedTasks() {
        return rejectedTasks.sum();
    }

    public long getProcessedTasks() {
        return processedTasks.sum();
    }

    public long getAverageProcessingTimeMs() {
        long processed = processedTasks.sum();
        if (processed == 0) return 0;
        return TimeUnit.NANOSECONDS.toMillis(totalProcessingTimeNs.sum() / processed);
    }

    public long getSlowTaskCount() {
        return slowTaskCount.sum();
    }

    public long getCriticalSlowTaskCount() {
        return criticalSlowTaskCount.sum();
    }

    public boolean isHealthy() {
        return !isClosing &&
                consecutiveSlowTasks.sum() < MAX_CONSECUTIVE_SLOW_TASKS &&
                taskQueue.size() < MAX_QUEUE_SIZE * 0.8;
    }

    @Override
    public void close() {
        disconnect();
    }
}
